# -*- coding: utf-8 -*-
import numpy
import json
from sklearn.neighbors import KNeighborsClassifier as kNN
import circle_cal

global rssi_group
with open('rssi_group.json', 'r') as f:
    global rssi_array
    rssi_list = json.loads(f.read())
    rssi_group = numpy.array(rssi_list)

global rssi_labels
with open('rssi_labels.json', 'r') as f:
    global rssi_array
    rssi_list = json.loads(f.read())
    rssi_labels = numpy.array(rssi_list)

rssi_group_size = len(rssi_group[0])
print('rssi_group:%d' % len(rssi_group))
print('rssi_group_size:%d' % rssi_group_size)
print('rssi_labels:%d' % len(rssi_labels))

# 构建KNN分类器
neigh = kNN(n_neighbors=3, weights='uniform', algorithm='auto')
# 拟合模型，trainingMat为测试矩阵,hwLabels为对应的标签
neigh.fit(rssi_group, rssi_labels)


def get_distance(rssi_num):
    rssi_num = numpy.array(rssi_num).reshape((1, -1))
    # print(vectorUnderTest)
    # 获得预测结果
    classifierResult = neigh.predict(rssi_num)
    # print(classifierResult)
    return classifierResult


def get_distance2(rssi_num):
    def cal(num):
        num = -0.008778245 * num ** 3 \
              - 2.158676003 * num ** 2 \
              - 177.065725 * num \
              - 4840.7079785
        if num < 0:
            num = 0
        if num > 20:
            num = -1
        return num

    result = [cal(num) for num in rssi_num]
    return result


def get_location(route_data_list):
    def cal_num(num1, num2):
        return num1 * num1 - num2 * num2

    # location = [[0, 0, 4.5], [10, 0, 74.5], [0, 10, 74.5], [2, 2, 0.5], [3, 3, 4.5], [4, 4, 12.5]]
    location = route_data_list
    location_len = len(location)
    A = numpy.empty((location_len - 1, 2))
    for i in range(location_len - 1):
        A[i][0] = 2 * (location[i][0] - location[location_len - 1][0])
        A[i][1] = 2 * (location[i][1] - location[location_len - 1][1])
    b = numpy.empty((location_len - 1, 1))
    for i in range(location_len - 1):
        b[i][0] = cal_num(location[i][0], location[location_len - 1][0]) \
                  + cal_num(location[i][1], location[location_len - 1][1]) \
                  + cal_num(location[location_len - 1][2], location[i][2])
    A = numpy.mat(A)
    b = numpy.mat(b)
    X = (A.T * A).I * A.T * b
    return X[0, 0], X[1, 0]


def test():
    err_num = 0
    all_num = len(rssi_group)
    for i in range(0, all_num):
        if len(rssi_group[i]) != rssi_group_size:
            print("rssi_group_size error %d" % i)
        if get_distance(rssi_group[i]) != i // (all_num // 10):
            err_num += 1
        # print(get_distance(rssi_group[i]),i//(all_num//10))
    print('错误率：%0.3f%%(%d/%d)' % (err_num * 100 / all_num, err_num, all_num))

#test()
# print(get_distance(rssi_group[1234]))
# print(get_distance2([num for num in range(-100, -50)]))
global route_list
route_list = None


def location_init(route_list_param):
    global route_list
    route_list = route_list_param
    for item in route_list:
        item.append(-1)


def location_measure(rssi_list):
    if route_list is None:
        return None
    route_data_list = []
    if isinstance(rssi_list, list) and isinstance(rssi_list[0], list):
        if len(rssi_list) == len(route_list):
            for i in range(len(rssi_list)):
                item = rssi_list[i]
                distance = []
                if len(item) > 0:
                    if len(item) == 20:
                        distance = get_distance(item)
                        print('distance type1')
                    else:
                        distance = get_distance2(item)
                        print('distance type2')
                if len(distance) > 0 and distance[0] >= 0:
                    route_list[i][2] = distance[0]
                    route_data_list.append(route_list[i])
                else:
                    route_list[i][2] = -1
    if len(route_data_list) > 0:
        # print(route_data_list)
        if len(route_data_list) >= 3:
            return get_location(route_data_list), 0, 0, len(route_data_list)
        elif len(route_data_list) == 2:
            return circle_cal.cal(route_data_list[0][0], route_data_list[0][1],
                                  route_data_list[1][0], route_data_list[1][1],
                                  route_data_list[0][2], route_data_list[1][2]), \
                   0, 0, 2
        else:
            return (route_data_list[0][0], route_data_list[0][1], route_data_list[0][2]), 0, 0, 1
    return None

# def test2():
#     location_init([[0, 0], [0, 10], [5, 5]])
#     rssi_list = [list(rssi_group[250 * 6 + 2]), list(rssi_group[250 * 8 + 2]), list(rssi_group[250 * 3 + 2])]
#     print(location_measure(rssi_list))
#     rssi_list = [[], list(rssi_group[250 * 8 + 2]), list(rssi_group[250 * 3 + 2])]
#     print(location_measure(rssi_list))
#     rssi_list = [[], [], list(rssi_group[250 * 3 + 2])]
#     print(location_measure(rssi_list))

# print(','.join(str(i) for i in rssi_group[250 * 6 + 2]))
# print(','.join(str(i) for i in rssi_group[250 * 8 + 2]))
# print(','.join(str(i) for i in rssi_group[250 * 3 + 2]))
# print(get_distance(list(rssi_group[250 * 8 + 2])))
# print(get_distance2(list(rssi_group[250 * 8 + 2])))
# test2()
